package org.devocean.groupbuying.dao.impl;

import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.devocean.groupbuying.dao.MerchantDAO;
import org.devocean.groupbuying.domain.ArticlesLocalization;
import org.devocean.groupbuying.domain.Merchant;
import org.springframework.stereotype.Repository;

@Repository
public class MerchantDAOImpl implements MerchantDAO{

	@PersistenceContext
	private EntityManager em;
	
	private String slugify(String string) {
		return Normalizer.normalize(string.toLowerCase(), Form.NFD)
				.replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
				.replaceAll("[^\\p{Alnum}]+", "_");
	}
	
	public List<Merchant> findAllMerchants() {
		
		return em.createQuery("select m from Merchant m", Merchant.class)
				.getResultList();
	}

	public long countMerchants() {
		
		return em.createQuery("SELECT COUNT(m)  FROM Merchant m", Long.class)
				.getSingleResult();
	}

	public List<Merchant> findMerchantsEntries(int firstResult, int maxResults) {
		
		 return em.createQuery("SELECT m FROM Merchant m ", Merchant.class)
				.setFirstResult(firstResult).setMaxResults(maxResults)
				.getResultList();
	}

	public Merchant findMerchantById(int id) {
		return em.find(Merchant.class, id);
	}

	public void deleteMerchant(int id) {
		final Merchant merchant = em.find(Merchant.class, id);

		if (merchant != null) {

			em.remove(merchant);
		}

	}

	public Merchant saveMerchant(Merchant merchant) {
		if (merchant.getArticlesLocalization().getArticlesLocalizationID() == null) {
			String title = merchant.getArticlesLocalization().getArticles()
					.iterator().next().getTitle();
			merchant.getArticlesLocalization().setPermalink(this.slugify(title));
		}
		em.persist(merchant);
		em.flush();
		return merchant;
	}

	public Merchant updateMerchant(Merchant merchant) {
		final Merchant merged = em.merge(merchant);
		return merged;
	}

	public List<Merchant> findMerchantByCriteria(String criteria, Integer start,
			Integer size) {
		
			Query query = em.createQuery("SELECT m FROM Merchant m INNER JOIN FETCH m.articlesLocalization al")
					.setFirstResult(start).setMaxResults(size);
			
			List<Merchant> merchants = query.getResultList();
			try{
			Set<Integer> idset = new HashSet<Integer>();
			for (Merchant merchant : merchants) {
				idset.add(merchant.getArticlesLocalization().getArticlesLocalizationID());
			}
			try {
				List<ArticlesLocalization> articlesLocalizations = em
						.createQuery(
								"SELECT al FROM ArticlesLocalization al INNER JOIN FETCH al.articles a WHERE a.title like :criteria AND al.articlesLocalizationID IN (:x)",
								ArticlesLocalization.class)
						.setParameter("criteria",criteria+"%").setParameter("x", idset)
						.getResultList();
	
			} catch (Exception e) {
				e.printStackTrace();
			}
		}catch (Exception e) {
			e.printStackTrace();
		}

	
		 return merchants;
	}

	public long countMerchantsByCriteria(String criteria) {
		
		 return em.createQuery("select COUNT(m) from Merchant m INNER JOIN m.articlesLocalization al INNER JOIN al.articles a  where a.title like :criteria",Long.class).setParameter("criteria",criteria+"%").getSingleResult();
	}

}
